package com.zhaotianhao.rentingservice.controller;


import cn.hutool.core.util.IdUtil;
import cn.hutool.jwt.JWT;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageInfo;
import com.zhaotianhao.rentingservice.api.TypeApi;
import com.zhaotianhao.rentingservice.common.HighLightResultMapper;
import com.zhaotianhao.rentingservice.common.JsonResult;
import com.zhaotianhao.rentingservice.common.WebUtils;
import com.zhaotianhao.rentingservice.dto.RentDTO;
import com.zhaotianhao.rentingservice.entity.Renting;
import com.zhaotianhao.rentingservice.entity.Type;
import com.zhaotianhao.rentingservice.mapper.RentingRepository;
import com.zhaotianhao.rentingservice.service.IRentingService;
import com.zhaotianhao.rentingservice.vo.RentVO;
import io.netty.util.internal.StringUtil;
import lombok.extern.slf4j.Slf4j;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.sort.SortBuilders;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
import org.springframework.data.elasticsearch.core.aggregation.AggregatedPage;
import org.springframework.data.elasticsearch.core.query.NativeSearchQuery;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.text.SimpleDateFormat;
import java.util.HashMap;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

/**
 * <p>
 *  前端控制器
 * </p>
 *
 * @author Z-7
 * @since 2022-05-16
 */
@Slf4j
@RestController
@RequestMapping("/renting")
public class RentingController {
    @Autowired
    private TypeApi typeApi;
    @Autowired
    private IRentingService iRentingService;
    @Autowired
    private KafkaTemplate kafkaTemplate;
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private RentingRepository rentingRepository;
    @Autowired
    private ElasticsearchTemplate elasticsearchTemplate;
    /**
     * es全量同步
     * @return
     */
    @GetMapping("getAll")
    public boolean getAll() {
        List<RentVO> all = iRentingService.getAll();
        all.forEach(rentVO -> {
            rentingRepository.save(rentVO);
        });
        return true;
    }

    @GetMapping("list")
    public JsonResult getList(RentDTO rentDTO, @RequestParam(defaultValue = "1")int pageNum,@RequestParam(defaultValue = "3")int pageSize) {
        BoolQueryBuilder query = QueryBuilders.boolQuery();
        // 租客
        if (StringUtils.hasText(rentDTO.getRenter())) {
            query.must(QueryBuilders.multiMatchQuery(rentDTO.getRenter(),"renter"));
        }
        // 类型
        if (rentDTO.getTypeId() != null) {
            query.must(QueryBuilders.termQuery("typeId",rentDTO.getTypeId()));
        }
        // 起始时间
        if (rentDTO.getStartRent() != null) {
            SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy/MM/dd");
            String format = simpleDateFormat.format(rentDTO.getStartRent());
            query.must(QueryBuilders.termQuery("startRent",format));
        }
        // 高亮字段
        HighlightBuilder.Field renter = new HighlightBuilder.Field("renter").preTags("<span style='color:red'>").postTags("</span>");
        NativeSearchQuery searchQuery = new NativeSearchQueryBuilder()
                .withQuery(query)
                .withHighlightFields(renter)
                .withPageable(PageRequest.of(pageNum - 1, pageSize))
                .withSort(SortBuilders.fieldSort("number").order(SortOrder.ASC))
                .build();
        AggregatedPage<RentVO> rentVOS = elasticsearchTemplate.queryForPage(searchQuery, RentVO.class, new HighLightResultMapper());
        // 总条数
        Page page = new Page(pageNum, pageSize);
        page.setTotal(rentVOS.getTotalElements());

        // 所有数据
        PageInfo<RentVO> rentVOPageInfo = new PageInfo<RentVO>(page);
        rentVOPageInfo.setList(rentVOS.getContent());

        return JsonResult.successd(rentVOPageInfo);
    }

    @GetMapping("getNumber")
    public JsonResult getNumber() {
        long number = IdUtil.getSnowflakeNextId();
        return JsonResult.successd(number);
    }

    @PostMapping("add")
    public JsonResult add(@RequestBody RentDTO rentDTO) throws InterruptedException {
        // 校验权限
        HttpServletRequest request = WebUtils.getRequest();
        String token = request.getHeader("token");
        JWT jwt = JWT.of(token).setKey("zhao".getBytes());
        Object role = jwt.getPayload("role");
        if (!"admin".equals(role.toString())) {
            log.info("只有管理员有新增权");
            return JsonResult.faild("权限不够");
        }
        // 防止表单重复提交
        if (!redisTemplate.opsForValue().setIfAbsent(rentDTO.getToken(),null,10, TimeUnit.SECONDS)) {
            log.info("表单重复提交");
            return JsonResult.faild("请稍等!!!");
        }
        // 线程睡眠1s
        Thread.sleep(1000);
        // 新增es
        RentVO rentVO = new RentVO();
        BeanUtils.copyProperties(rentDTO,rentVO);
        // 根据房源类型id查询类型名称
        Type type = typeApi.getById(rentDTO.getTypeId());
        if (type == null) {
            log.error("添加es出错");
            return JsonResult.faild("新增失败");
        }
        rentVO.setTypeName(type.getTypeName());
        RentVO save = rentingRepository.save(rentVO);
        if (save == null) {
            log.error("添加es出错");
            return JsonResult.faild("新增失败");
        }
        // 发送kafka消息
        String uuid = UUID.randomUUID().toString();
        kafkaTemplate.send("month",uuid, JSONObject.toJSONString(rentDTO));
        // 防止消息丢失
        HashMap<String, Object> map = new HashMap<>();
        map.put("message",JSONObject.toJSONString(rentDTO));
        map.put("create_time",System.currentTimeMillis());
        redisTemplate.opsForValue().set("message:"+uuid,JSONObject.toJSONString(map));

        return JsonResult.successd();
    }

    @GetMapping("getAllType")
    public JsonResult getAllType() {
        Object data = typeApi.getAllType().getData();
        List<Type> allType = JSON.parseArray(data.toString(), Type.class);
        return JsonResult.successd(allType);
    }
}
